home *** CD-ROM | disk | FTP | other *** search
/ Gold Medal Software 2 / Gold Medal Software Volume 2 (Gold Medal) (1994).iso / prog / asm_0_m.arj / FMT.ASM < prev    next >
Assembly Source File  |  1990-01-23  |  78KB  |  2,855 lines

  1. ;***********************************************************************
  2. ;*                                                                     *
  3. ;*  Fmt.asm                                             23-JAN-1990    *
  4. ;*                                                                     *
  5. ;*  Format Floppy Disk - version 1.00 - IBM(R) DOS 4.0 style format    *
  6. ;*                                                                     *
  7. ;*  Designed for use with IBM AT compatible sytems (including PS/2s)   *
  8. ;*                                                                     *
  9. ;*  Syntax: FMT d: size [v] [s] [n]                                    *
  10. ;*                                                                     *
  11. ;*    where: d = drive (A or B), size = floppy size in Kb,             *
  12. ;*                                                                     *
  13. ;*      the optional v enables format verification,                    *
  14. ;*                                                                     *
  15. ;*      the optional s copies the system files,                        *
  16. ;*                                                                     *
  17. ;*      and the optional n bypasses the `insert floppy' prompt         *
  18. ;*                                                                     *
  19. ;*    supported sizes are:                                             *
  20. ;*                                                                     *
  21. ;*      360 for a 360 Kb floppy in a 360 Kb or 1.2 Mb drive            *
  22. ;*      720 for a 720 Kb floppy in a 720 Kb or 1.44 Mb drive           *
  23. ;*      1200 for a 1.2 Mb floppy in a 1.2 Mb drive                     *
  24. ;*      1440 for a 1.44 Mb floppy in a 1.44 Mb drive                   *
  25. ;*                                                                     *
  26. ;*  Exit codes:                                                        *
  27. ;*                                                                     *
  28. ;*    0 = successful format                                            *
  29. ;*    1 = failure during format, verify, or write                      *
  30. ;*    2 = disk size / drive type combination is not supported          *
  31. ;*    3 = requested drive does not exist                               *
  32. ;*    4 = invalid or null command line                                 *
  33. ;*    5 = system files not found or error writing system files         *
  34. ;*    6 = computer is not AT compatible                                *
  35. ;*    7 = insufficient memory for file copy buffer (system transfer)   *
  36. ;*                                                                     *
  37. ;*  In order to use the system transfer option, the following files    *
  38. ;*                                                                     *
  39. ;*    must be in the root diectory of the default drive:               *
  40. ;*                                                                     *
  41. ;*      1: IBMBIO.COM (normally a hidden file)                         *
  42. ;*                                                                     *
  43. ;*      2: IBMDOS.COM (normally a hidden file)                         *
  44. ;*                                                                     *
  45. ;*      3: COMMAND.COM                                                 *
  46. ;*                                                                     *
  47. ;*  Compile with Borland Turbo Assembler(R) version 1.0 or greater     *
  48. ;*                                                                     *
  49. ;*      tasm /t fmt                     tasm /t /zi fmt                *
  50. ;*                              or                                     *
  51. ;*      tlink /t /x fmt                 tlink /v /x fmt                *
  52. ;*                                                                     *
  53. ;*                                      tdstrip -c -s fmt              *
  54. ;*                                                                     *
  55. ;*                                      for use with Turbo Debugger(R) *
  56. ;*    or                                                               *
  57. ;*                                                                     *
  58. ;*  Compile with Microsoft(R) Macro Assembler version 5.1 or greater   *
  59. ;*                                                                     *
  60. ;*      masm /t fmt;                                                   *
  61. ;*                                                                     *
  62. ;*      link fmt;                                                      *
  63. ;*                                                                     *
  64. ;*      exe2bin fmt fmt.com                                            *
  65. ;*                                                                     *
  66. ;*      del fmt.exe                                                    *
  67. ;*                                                                     *
  68. ;*  Copyright (C) 1990 by:                                             *
  69. ;*                                                                     *
  70. ;*  Clair Alan Hardesty                                                *
  71. ;*  IBM-PC Hardware/Software Consultant                                *
  72. ;*  10301 Johnson Av                                                   *
  73. ;*  Cupertino, CA 95014                                                *
  74. ;*  (408) 446-0550                                                     *
  75. ;*  CompuServe 75350,16                                                *
  76. ;*                                                                     *
  77. ;*  Microsoft(R) is a registered trademark of Microsoft Corporation    *
  78. ;*                                                                     *
  79. ;*  IBM(R) and PS/2 are registered trademarks of International         *
  80. ;*                                                                     *
  81. ;*   Business Machines Corporation                                     *
  82. ;*                                                                     *
  83. ;*  Turbo Assembler(R) and Turbo Debugger(R) are registered trademarks *
  84. ;*                                                                     *
  85. ;*   of Borland International                                          *
  86. ;*                                                                     *
  87. ;***********************************************************************
  88.  
  89. ;***********************************************************************
  90.  
  91.                 ; set-up for the far jump used in the boot record code
  92.  
  93. ;***********************************************************************
  94.  
  95. ibmbio          segment at 0070h
  96.  
  97.                 assume cs:ibmbio
  98.  
  99.                 org 0000h
  100.  
  101. program_loader  label far
  102.  
  103. ibmbio          ends
  104.  
  105. ;***********************************************************************
  106.  
  107.                 ; set-up for system identification
  108.  
  109. ;***********************************************************************
  110.  
  111. rom_bios        segment at 0f000h
  112.  
  113.                 assume ds:rom_bios
  114.  
  115.                 org 0fffeh
  116.  
  117. system_id       label byte
  118.  
  119. rom_bios        ends
  120.  
  121. ;***********************************************************************
  122.  
  123.                 ; main program code
  124.  
  125. ;***********************************************************************
  126.  
  127. cseg            segment
  128.  
  129.                 assume cs:cseg,ds:cseg,es:cseg,ss:cseg
  130.  
  131.                 org 0100h
  132. entry_point:
  133.                 jmp start               ; skip over data area
  134.  
  135. ;***********************************************************************
  136.  
  137.                 ; format data area
  138.  
  139. ;***********************************************************************
  140.  
  141.                 ; format sector tables
  142. sector_table_0:
  143.                 db 000h,000h,001h,002h
  144.                 db 000h,000h,002h,002h
  145.                 db 000h,000h,003h,002h
  146.                 db 000h,000h,004h,002h
  147.                 db 000h,000h,005h,002h
  148.                 db 000h,000h,006h,002h
  149.                 db 000h,000h,007h,002h
  150.                 db 000h,000h,008h,002h
  151.                 db 000h,000h,009h,002h
  152.                 db 000h,000h,00Ah,002h
  153.                 db 000h,000h,00Bh,002h
  154.                 db 000h,000h,00Ch,002h
  155.                 db 000h,000h,00Dh,002h
  156.                 db 000h,000h,00Eh,002h
  157.                 db 000h,000h,00Fh,002h
  158.                 db 000h,000h,010h,002h
  159.                 db 000h,000h,011h,002h
  160.                 db 000h,000h,012h,002h
  161.  
  162. sector_table_1:
  163.                 db 000h,001h,001h,002h
  164.                 db 000h,001h,002h,002h
  165.                 db 000h,001h,003h,002h
  166.                 db 000h,001h,004h,002h
  167.                 db 000h,001h,005h,002h
  168.                 db 000h,001h,006h,002h
  169.                 db 000h,001h,007h,002h
  170.                 db 000h,001h,008h,002h
  171.                 db 000h,001h,009h,002h
  172.                 db 000h,001h,00Ah,002h
  173.                 db 000h,001h,00Bh,002h
  174.                 db 000h,001h,00Ch,002h
  175.                 db 000h,001h,00Dh,002h
  176.                 db 000h,001h,00Eh,002h
  177.                 db 000h,001h,00Fh,002h
  178.                 db 000h,001h,010h,002h
  179.                 db 000h,001h,011h,002h
  180.                 db 000h,001h,012h,002h
  181.  
  182. ;***********************************************************************
  183.  
  184. temp_size:      db 4 dup (?)
  185. binary_size:    dw ?
  186. verify:         db 0            ; default is no verification
  187. system:         db 0            ; default is no system file transfer
  188. prompt:         db 1            ; default is prompt for floppy
  189. drive_number:   db ?
  190. disk_drive:     dw ?
  191. max_track:      db ?
  192. retry_count:    db ?
  193. write_track:    dw ?
  194. write_head:     db ?
  195. write_sector:   db ?
  196. cursor:         dw ?
  197. stack_size:     dw 2048         ; used in buffer size calculation
  198. minimum_buffer: dw 4096         ; minimum file copy buffer size
  199. buffer_size:    dw ?            ; actual file copy buffer size
  200.  
  201. ;***********************************************************************
  202.  
  203. disk_size:      db ?
  204.  
  205.                 ; 1 = 360kb
  206.                 ; 2 = 1.2Mb
  207.                 ; 3 = 720kb
  208.                 ; 4 = 1.44Mb
  209.  
  210. drive_type:     db ?
  211.  
  212.                 ; 0 = no drive
  213.                 ; 1 = 360kb
  214.                 ; 2 = 1.2Mb
  215.                 ; 3 = 720kb
  216.                 ; 4 = 1.44Mb
  217.  
  218. ;***********************************************************************
  219.  
  220. parameter_pointer:
  221.  
  222.         dd ?    ; storage for the original disk parameter table pointer
  223.  
  224. ;***********************************************************************
  225.  
  226. floppy_table:
  227.                 ; 360 Kb
  228.  
  229.                 db 0FDh         ; media descriptor
  230.                 db 40           ; number of tracks
  231.                 dw 9            ; sectors per track
  232.                 dw 112          ; entries per root directory
  233.                 db 7            ; sectors per root directory
  234.                 db 2            ; sectors per cluster
  235.                 dw 2            ; sectors per FAT
  236.  
  237.                 ; 1.2 Mb
  238.  
  239.                 db 0F9h         ; media descriptor
  240.                 db 80           ; number of tracks
  241.                 dw 15           ; sectors per track
  242.                 dw 224          ; entries per root directory
  243.                 db 14           ; sectors per root directory
  244.                 db 1            ; sectors per cluster
  245.                 dw 7            ; sectors per FAT
  246.  
  247.                 ; 720 Kb
  248.  
  249.                 db 0F9h         ; media descriptor
  250.                 db 80           ; number of tracks
  251.                 dw 9            ; sectors per track
  252.                 dw 112          ; entries per root directory
  253.                 db 7            ; sectors per root directory
  254.                 db 2            ; sectors per cluster
  255.                 dw 3            ; sectors per FAT
  256.  
  257.                 ; 1.44 Mb
  258.  
  259.                 db 0F0h         ; media descriptor
  260.                 db 80           ; number of tracks
  261.                 dw 18           ; sectors per track
  262.                 dw 224          ; entries per root directory
  263.                 db 14           ; sectors per root directory
  264.                 db 1            ; sectors per cluster
  265.                 dw 9            ; sectors per FAT
  266.  
  267. ;***********************************************************************
  268.  
  269. parameter_table:
  270.  
  271.         ; 360 Kb
  272.  
  273.         db 0D2h,002h,009h,002h,009h,02Ah,0FFh,050h,0F6h,001h,001h
  274.  
  275.         ; 1.2 Mb
  276.  
  277.         db 082h,002h,009h,002h,00Fh,01Bh,0FFh,054h,0F6h,001h,001h
  278.  
  279.         ; 720 Kb
  280.  
  281.         db 012h,002h,009h,002h,009h,02Ah,0FFh,050h,0F6h,001h,001h
  282.  
  283.         ; 1.44 Mb
  284.  
  285.         db 012h,002h,009h,002h,012h,01Bh,0FFh,06Ch,0F6h,001h,001h
  286.  
  287. ;***********************************************************************
  288.  
  289.         ; informational messages
  290.  
  291. ;***********************************************************************
  292.  
  293. cr_lf:
  294.         db 00Dh,00Ah
  295.         db "$"
  296.  
  297. insert_floppy:
  298.  
  299.         db "Put desired floppy in drive "
  300.  
  301.     insert_drive:
  302.  
  303.         db ?
  304.         db ": and press any key"
  305.         db "$"
  306.  
  307. clear_line:
  308.  
  309.         db 50 dup (008h)
  310.         db 50 dup (020h)
  311.         db 50 dup (008h)
  312.         db "$"
  313.  
  314. format_display:
  315.  
  316.         db 26 dup (008h)
  317.         db "Formatting track "
  318.  
  319.     format_track_number:
  320.  
  321.         db 2 dup (?)
  322.         db " head "
  323.  
  324.     format_head_number:
  325.  
  326.         db ?
  327.         db "$"
  328.  
  329. verify_display:
  330.  
  331.         db 26 dup (008h)
  332.         db "Verifying  track "
  333.  
  334.     verify_track_number:
  335.  
  336.         db 2 dup (?)
  337.         db " head "
  338.  
  339.     verify_head_number:
  340.  
  341.         db ?
  342.         db "$"
  343.  
  344. boot_message:
  345.  
  346.         db 26 dup (008h)
  347.         db 26 dup (020h)
  348.         db 26 dup (008h)
  349.         db "Writing boot record"
  350.         db "$"
  351.  
  352. fat_message:
  353.  
  354.         db 19 dup (008h)
  355.         db 19 dup (020h)
  356.         db 19 dup (008h)
  357.         db "Writing FATs"
  358.         db "$"
  359.  
  360. dir_message:
  361.  
  362.         db 12 dup (008h)
  363.         db 12 dup (020h)
  364.         db 12 dup (008h)
  365.         db "Writing root directory"
  366.         db "$"
  367.  
  368. file_copy_message:
  369.  
  370.         db 22 dup (008h)
  371.         db 22 dup (020h)
  372.         db 22 dup (008h)
  373.         db "Copying system files"
  374.         db "$"
  375.  
  376. exit_message:
  377.  
  378.         db 22 dup (008h)
  379.         db 22 dup (020h)
  380.         db 22 dup (008h)
  381.         db "Format complete"
  382.         db 00Dh,00Ah
  383.         db "$"
  384.  
  385. ;***********************************************************************
  386.  
  387.         ; error messages
  388.  
  389. ;***********************************************************************
  390.  
  391. computer_message:
  392.  
  393.         db 00Dh,00Ah,"IBM AT or compatible computer required",00Dh,00Ah
  394.         db "$"
  395.  
  396. no_drive_error:
  397.  
  398.         db 00Dh,00Ah,"No such drive in system",00Dh,00Ah
  399.         db "$"
  400.  
  401. reset_error:
  402.  
  403.         db 00Dh,00Ah,"Disk controller reset error",00Dh,00Ah
  404.         db "$"
  405.  
  406. set_drive_error:
  407.  
  408.         db 00Dh,00Ah,"Disk drive type not supported by BIOS",00Dh,00Ah
  409.         db "$"
  410.  
  411. no_floppy_error:
  412.  
  413.         db 00Dh,00Ah,"No floppy in drive",00Dh,00Ah
  414.         db "$"
  415.  
  416. set_disk_error:
  417.  
  418.         db 00Dh,00Ah,"Disk / Drive combination not supported",00Dh,00Ah
  419.         db "$"
  420.  
  421. write_boot_error:
  422.  
  423.         db 00Dh,00Ah,"Error writing boot record",00Dh,00Ah
  424.         db "$"
  425.  
  426. write_fat_error:
  427.  
  428.         db 00Dh,00Ah,"Error writing FAT",00Dh,00Ah
  429.         db "$"
  430.  
  431. write_dir_error:
  432.  
  433.         db 00Dh,00Ah,"Error writing directory",00Dh,00Ah
  434.         db "$"
  435.  
  436. write_protect_error:
  437.  
  438.         db 00Dh,00Ah,"Disk is write protected",00Dh,00Ah
  439.         db "$"
  440.  
  441. error_during_format:
  442.  
  443.         db 00Dh,00Ah,"Error during format",00Dh,00Ah
  444.         db "$"
  445.  
  446. disk_type_error:
  447.  
  448.         db 00Dh,00Ah,"Probably wrong floppy type",00Dh,00Ah
  449.         db "$"
  450.  
  451. verify_error:
  452.  
  453.         db 00Dh,00Ah,"Verification error",00Dh,00Ah
  454.         db "$"
  455.  
  456. buffer_space_error:
  457.  
  458.         db 00Dh,00Ah,"No room for file copy buffer",00Dh,00Ah
  459.         db "$"
  460.  
  461. help_message:
  462.  
  463. db 00Dh,00Ah,"FMT version 1.00, Copyright (C) 1990 Clair Alan Hardesty"
  464. db 00Dh,00Ah
  465. db 00Dh,00Ah," syntax: fmt d: size [v] [s] [n]"
  466. db 00Dh,00Ah
  467. db 00Dh,00Ah,"  where: d = drive (A or B), size = floppy size in Kb,"
  468. db 00Dh,00Ah
  469. db 00Dh,00Ah,"   the optional v enables format verification,"
  470. db 00Dh,00Ah
  471. db 00Dh,00Ah,"   the optional s copies the system files,"
  472. db 00Dh,00Ah
  473. db 00Dh,00Ah,"   and the optional n bypasses the `insert floppy' prompt"
  474. db 00Dh,00Ah
  475. db 00Dh,00Ah,"  supported sizes are:"
  476. db 00Dh,00Ah
  477. db 00Dh,00Ah,"   360 for a 360 Kb floppy in a 360 Kb or 1.2 Mb drive"
  478. db 00Dh,00Ah,"   720 for a 720 Kb floppy in a 720 Kb or 1.44 Mb drive"
  479. db 00Dh,00Ah,"   1200 for a 1.2 Mb floppy in a 1.2 Mb drive"
  480. db 00Dh,00Ah,"   1440 for a 1.44 Mb floppy in a 1.44 Mb drive"
  481. db 00Dh,00Ah
  482. db "$"
  483.  
  484. ;***********************************************************************
  485.  
  486.                 ; check cpu and computer type
  487.  
  488. ;***********************************************************************
  489.  
  490. start:
  491.                 ; check CPU for 80286 or above
  492.  
  493.                 xor     ax,ax
  494.                 push    ax
  495.                 popf
  496.                 pushf
  497.                 pop     ax
  498.                 and     ax,08000h
  499.                 cmp     ax,08000h
  500.  
  501.                 jnz two_eighty_six
  502.  
  503.                 mov dx,offset computer_message
  504.                 mov ah,09h
  505.  
  506.                 int 21h
  507.  
  508.                 ; exit
  509.  
  510.                 jmp short not_an_at
  511. two_eighty_six:
  512.                 ; check the model byte in ROM
  513.  
  514.                 push ds
  515.                 mov ax,rom_bios
  516.                 mov ds,ax
  517.  
  518.                 assume ds:rom_bios
  519.  
  520.                 cmp system_id,0fch      ; AT or compatible
  521.  
  522.                 je at_or_better
  523.  
  524.                 cmp system_id,0fah      ; most P/S-2 (80286) models
  525.  
  526.                 je at_or_better
  527.  
  528.                 cmp system_id,0f8h      ; P/S-2 model 80
  529.  
  530.                 je at_or_better
  531.  
  532.                 ; computer is not AT compatible
  533.  
  534.                 pop ds
  535.  
  536.                 assume ds:cseg
  537.  
  538.                 mov dx,offset computer_message
  539.                 mov ah,09h
  540.  
  541.                 int 21h
  542. not_an_at:
  543.                 ; set exit code to 6 (not an AT or compatible)
  544.  
  545.                 mov ax,4c06h
  546.  
  547.                 int 21h
  548.  
  549. at_or_better:
  550.  
  551. ;***********************************************************************
  552.  
  553. .286            ; enable the 80286 instruction set
  554.  
  555. ;***********************************************************************
  556.  
  557.                 pop ds
  558.  
  559.                 assume ds:cseg
  560.  
  561.                 ; initialize some variables
  562.  
  563.                 mov cl,0                ; parameter counter
  564.                 mov dl,0                ; disk size digit counter
  565.                 mov di,offset temp_size ; temporary disk size storage
  566.                 mov bx,0080h            ; pointer to command line
  567.  
  568. ;***********************************************************************
  569.  
  570.                 ; parse the command line
  571.  
  572. ;***********************************************************************
  573.  
  574. parse_loop:
  575.                 inc bx
  576.                 cmp byte ptr [bx],0dh   ; carriage return
  577.  
  578.                 jne not_finished
  579.  
  580.                 jmp got_command
  581. not_finished:
  582.                 cmp byte ptr [bx],' '   ; space
  583.  
  584.                 je parse_loop
  585.  
  586.                 cmp byte ptr [bx],09h   ; tab
  587.  
  588.                 je parse_loop
  589.  
  590.                 cmp cl,0
  591.  
  592.                 jg number_check
  593.  
  594.                 and byte ptr [bx],5fh   ; capitalize drive letter
  595.                 cmp byte ptr [bx],'A'
  596.  
  597.                 jnl check_for_b
  598.  
  599.                 jmp help                ; invalid drive
  600. check_for_b:
  601.                 cmp byte ptr [bx],'B'
  602.  
  603.                 jng store_drive
  604.  
  605.                 jmp help                ; invalid drive
  606. store_drive:
  607.                 mov al,byte ptr [bx]
  608.                 sub al,'A'
  609.                 mov byte ptr [drive_number],al
  610. colon_check:
  611.                 cmp byte ptr [bx+1],':'
  612.  
  613.                 je found_colon
  614.  
  615.                 jmp help                ; no colon after drive letter
  616. found_colon:
  617.                 inc bx                  ; skip over the colon
  618.                 inc cl                  ; increment parameter count
  619.  
  620.                 jmp parse_loop
  621. number_check:
  622.                 cmp cl,1
  623.  
  624.                 jg check_option
  625.  
  626.                 cmp byte ptr [bx],'0'
  627.  
  628.                 jnl maybe_a_number
  629.  
  630.                 jmp help                ; not a number
  631. maybe_a_number:
  632.                 cmp byte ptr [bx],'9'
  633.  
  634.                 jng is_a_number
  635.  
  636.                 jmp help                ; not a number
  637. is_a_number:
  638.                 cmp byte ptr [bx+1],0Dh ; next character is a return
  639.  
  640.                 je last_digit
  641.  
  642.                 cmp byte ptr [bx+1],' ' ; next character is a space
  643.  
  644.                 je last_digit
  645.  
  646.                 cmp byte ptr [bx+1],09h ; next character is a tab
  647.  
  648.                 jne store_digit
  649. last_digit:
  650.                 inc cl                  ; increment parameter count
  651. store_digit:
  652.                 mov al,byte ptr [bx]
  653.                 sub al,'0'              ; convert ASCII to BCD
  654.                 mov byte ptr [di],al
  655.                 inc di
  656.                 inc dl
  657.                 cmp dl,4
  658.  
  659.                 jle jump_to_parse
  660.  
  661.                 jmp help                ; too many digits in disk size
  662. jump_to_parse:
  663.                 jmp parse_loop
  664. check_option:
  665.                 cmp cl,5
  666.  
  667.                 jng parse_option
  668.  
  669.                 jmp help                ; too many parameters
  670. parse_option:
  671.                 and byte ptr [bx],5fh
  672.                 cmp byte ptr [bx],'V'
  673.  
  674.                 je set_verify
  675.  
  676.                 cmp byte ptr [bx],'S'
  677.  
  678.                 je set_system
  679.  
  680.                 cmp byte ptr [bx],'N'
  681.  
  682.                 je clear_prompt
  683.  
  684.                 jmp help                ; invalid option
  685. set_verify:
  686.                 mov byte ptr [verify],1 ; set format verify true
  687.                 inc cl
  688.  
  689.                 jmp parse_loop
  690. set_system:
  691.                 mov byte ptr [system],1 ; set transfer system true
  692.                 inc cl
  693.  
  694.                 jmp parse_loop
  695. clear_prompt:
  696.                 mov byte ptr [prompt],0 ; set transfer system true
  697.                 inc cl
  698.  
  699.                 jmp parse_loop
  700. got_command:
  701.                 cmp cl,2
  702.  
  703.                 jnl two_parameters
  704.  
  705.                 jmp help                ; too few parameters
  706. two_parameters:
  707.                 cmp dl,3
  708.  
  709.                 jl help                 ; too few digits in disk size
  710.  
  711.                 ; convert the size parameter from BCD to binary
  712.  
  713.                 mov cl,dl
  714.                 dec di
  715.                 xor ah,ah
  716.                 mov al,byte ptr [di]
  717.                 mov word ptr [binary_size],ax
  718.                 dec di
  719.                 dec cl
  720.                 xor ah,ah
  721.                 mov al,byte ptr [di]
  722.                 imul ax,10
  723.                 add word ptr [binary_size],ax
  724.                 dec di
  725.                 dec cl
  726.                 xor ah,ah
  727.                 mov al,byte ptr [di]
  728.                 imul ax,100
  729.                 add word ptr [binary_size],ax
  730.                 dec di
  731.                 dec cl
  732.  
  733.                 jz test_size_360
  734.  
  735.                 xor ah,ah
  736.                 mov al,byte ptr [di]
  737.                 imul ax,1000
  738.                 add word ptr [binary_size],ax
  739. test_size_360:
  740.                 cmp word ptr [binary_size],360
  741.  
  742.                 jne test_size_1200              ; not 360 Kb
  743.  
  744.                 mov byte ptr [disk_size],1
  745.  
  746.                 jmp short set_up                ; command line is valid
  747. test_size_1200:
  748.                 cmp word ptr [binary_size],1200
  749.  
  750.                 jne test_size_720               ; not 1.2 Mb
  751.  
  752.                 mov byte ptr [disk_size],2
  753.  
  754.                 jmp short set_up                ; command line is valid
  755. test_size_720:
  756.                 cmp word ptr [binary_size],720
  757.  
  758.                 jne test_size_1440              ; not 720 Kb
  759.  
  760.                 mov byte ptr [disk_size],3
  761.  
  762.                 jmp short set_up                ; command line is valid
  763. test_size_1440:
  764.                 cmp word ptr [binary_size],1440
  765.  
  766.                 jne help                        ; not 1.44 Mb
  767.  
  768.                 mov byte ptr [disk_size],4
  769.  
  770.                 jmp short set_up                ; command line is valid
  771. help:
  772.                 ; command line is invalid or null
  773.  
  774.                 mov dx,offset help_message
  775.                 mov ah,09h
  776.  
  777.                 int 21h
  778.  
  779.                 ; set exit code to 4 (null or invalid command line)
  780.  
  781.                 mov ax,4c04h
  782.  
  783.                 int 21h
  784.  
  785. ;***********************************************************************
  786.  
  787.                 ; set up the drive parameters and the parameter table
  788.  
  789. ;***********************************************************************
  790.  
  791. set_up:
  792.                 ; if transfering system, check file copy buffer space
  793.  
  794.                 cmp byte ptr [system],1
  795.  
  796.                 jne cursor_off
  797.  
  798.                 ; calculate copy buffer size
  799.  
  800.                 mov ax,sp
  801.                 cmp ax,offset file_buffer
  802.  
  803.                 jc no_buffer
  804.  
  805.                 sub ax,offset file_buffer
  806.                 sbb ax,word ptr [stack_size]
  807.  
  808.                 jc no_buffer
  809.  
  810.                 cmp ax,word ptr [minimum_buffer]
  811.  
  812.                 jnc buffer_ok
  813. no_buffer:
  814.                 mov dx,offset buffer_space_error
  815.                 mov ah,09h
  816.  
  817.                 int 21h
  818.  
  819.                 ; set exit code to 7 (no room for file copy buffer)
  820.  
  821.                 mov ax,4c07h
  822.  
  823.                 int 21h
  824. buffer_ok:
  825.                 mov word ptr [buffer_size],ax
  826. cursor_off:
  827.                 ; save the current cursor and then turn the cursor off
  828.  
  829.                 mov ah,03h
  830.  
  831.                 int 10h
  832.  
  833.                 mov word ptr [cursor],cx
  834.                 or cx,2000h
  835.                 mov ah,01h
  836.  
  837.                 int 10h
  838.  
  839.                 ; issue a carrriage-return / line-feed to stdout
  840.  
  841.                 mov dx,offset cr_lf
  842.                 mov ah,09h
  843.  
  844.                 int 21h
  845.  
  846.                 ; check for prompt bypass
  847.  
  848.                 cmp byte ptr [prompt],1
  849.  
  850.                 jne no_prompt
  851.  
  852.                 ; prompt for a floppy
  853.  
  854.                 mov dx,offset insert_floppy
  855.                 mov ah,09h
  856.                 mov al,byte ptr [drive_number]
  857.                 add al,41h
  858.                 mov byte ptr [insert_drive],al
  859.  
  860.                 int 21h
  861.  
  862.                 ; wait for a key press
  863.  
  864.                 xor ah,ah
  865.  
  866.                 int 16h
  867.  
  868.                 ; clear the message line
  869.  
  870.                 mov dx,offset clear_line
  871.                 mov ah,09h
  872.                 int 21h
  873. no_prompt:
  874.                 ; get disk drive information
  875.  
  876.                 push es
  877.                 push di
  878.                 push si
  879.                 mov ah,08h
  880.                 mov dl,byte ptr [drive_number]
  881.  
  882.                 int 13h
  883.  
  884.                 cmp bl,0
  885.  
  886.                 jne drive_exists
  887.  
  888.                 mov dx,offset no_drive_error
  889.                 mov ah,09h
  890.  
  891.                 int 21h
  892.  
  893.                 ; set exit code to 3 (drive does not exist)
  894.  
  895.                 pop ax
  896.                 pop ax
  897.                 pop ax
  898.                 mov ax,4c03h
  899.  
  900.                 int 21h
  901. drive_exists:
  902.                 mov byte ptr [max_track],ch
  903.                 mov byte ptr [sectors_track],cl
  904.                 mov byte ptr [drive_type],bl
  905.                 mov ah,byte ptr [disk_size]
  906.                 mov al,bl
  907.                 mov word ptr [disk_drive],ax
  908.  
  909.                 ; check for floppy size less than drive maximum capacity
  910.  
  911.                 ; check for a 360 Kb floppy in a 1.2 Mb drive
  912.  
  913.                 cmp word ptr [disk_drive],0102h
  914.  
  915.                 je forty_tracks
  916.  
  917.                 ; check for a 720 Kb floppy in a 1.44 Mb drive
  918.  
  919.                 cmp word ptr [disk_drive],0304h
  920.  
  921.                 je nine_sectors
  922.  
  923.                 ; check for improper disk / drive cominations
  924.  
  925.                 cmp word ptr [disk_drive],0201h
  926.  
  927.                 je bad_size                     ; 1.2 Mb in 360 Kb
  928.  
  929.                 cmp word ptr [disk_drive],0301h
  930.  
  931.                 je bad_size                     ; 720 Kb in 360 Kb
  932.  
  933.                 cmp word ptr [disk_drive],0401h
  934.  
  935.                 je bad_size                     ; 1.44 Mb in 360 Kb
  936.  
  937.                 cmp word ptr [disk_drive],0302h
  938.  
  939.                 je bad_size                     ; 720 Kb in 1.2 Mb
  940.  
  941.                 cmp word ptr [disk_drive],0402h
  942.  
  943.                 je bad_size                     ; 1.44 Mb in 1.2 Mb
  944.  
  945.                 cmp word ptr [disk_drive],0103h
  946.  
  947.                 je bad_size                     ; 360 Kb in 720 Kb
  948.  
  949.                 cmp word ptr [disk_drive],0203h
  950.  
  951.                 je bad_size                     ; 1.2 Mb in 720 Kb
  952.  
  953.                 cmp word ptr [disk_drive],0403h
  954.  
  955.                 je bad_size                     ; 1.44 Mb in 720 Kb
  956.  
  957.                 cmp word ptr [disk_drive],0104h
  958.  
  959.                 je bad_size                     ; 360 Kb in 1.44 Mb
  960.  
  961.                 cmp word ptr [disk_drive],0204h
  962.  
  963.                 je bad_size                     ; 1.2 Mb in 1.44 Mb
  964.  
  965.                 jmp short size_ok
  966. bad_size:
  967.                 mov dx,offset set_disk_error
  968.                 mov ah,09h
  969.  
  970.                 int 21h
  971.  
  972.                 ; set exit code to 2 (disk / drive comination error)
  973.  
  974.                 pop ax
  975.                 pop ax
  976.                 pop ax
  977.                 mov ax,4c02h
  978.  
  979.                 int 21h
  980. forty_tracks:
  981.                 mov byte ptr [max_track],39
  982. nine_sectors:
  983.                 mov byte ptr [sectors_track],9
  984. size_ok:
  985.                 ; save the original disk parameter table pointer
  986.  
  987.                 xor ax,ax
  988.                 mov es,ax
  989.                 mov ax,word ptr es:[0078h]
  990.                 mov dx,word ptr es:[007ah]
  991.                 mov word ptr [parameter_pointer],ax
  992.                 mov word ptr [parameter_pointer+2],dx
  993.  
  994.                 ; set the disk parameter table pointer for formatting
  995.  
  996.                 xor ah,ah
  997.                 mov al,byte ptr [disk_size]
  998.                 dec ax
  999.                 imul ax,11
  1000.                 add ax,offset parameter_table
  1001.                 cli
  1002.                 mov word ptr es:[0078h],ax
  1003.                 mov word ptr es:[007ah],cs
  1004.                 sti
  1005.  
  1006.                 ; put the parameter table in the boot record
  1007.  
  1008.                 push cs
  1009.                 pop es
  1010.                 mov si,ax
  1011.                 mov di,offset disk_table
  1012.                 mov cx,11
  1013.                 cld
  1014.  
  1015.                 rep movsb
  1016.  
  1017.                 pop si
  1018.                 pop di
  1019.                 pop es
  1020.  
  1021. ;***********************************************************************
  1022.  
  1023.                 ; store the disk parameters in the boot record and FAT
  1024.  
  1025. ;***********************************************************************
  1026.  
  1027.                 push si
  1028.  
  1029.                 ; calculate the offset to the parameters in floppy_table
  1030.  
  1031.                 xor ah,ah
  1032.                 mov al,byte ptr [disk_size]
  1033.                 dec ax
  1034.                 imul ax,10
  1035.                 mov bx,ax
  1036.                 mov si,offset floppy_table
  1037.  
  1038.                 ; set the media descriptor byte
  1039.  
  1040.                 mov al,byte ptr [si+bx]
  1041.                 mov byte ptr [descriptor],al
  1042.                 mov byte ptr [fat_record],al    ; first byte of FAT
  1043.  
  1044.                 ; set the number of root directory entries
  1045.  
  1046.                 mov ax,word ptr [si+bx+4]
  1047.                 mov word ptr [directory_size],ax
  1048.  
  1049.                 ; set the number of sectors per directory
  1050.  
  1051.                 mov al,byte ptr [si+bx+6]
  1052.                 mov byte ptr [sectors_directory],al
  1053.  
  1054.                 ; set the number of sectors per cluster
  1055.  
  1056.                 mov al,byte ptr [si+bx+7]
  1057.                 mov byte ptr [sectors_cluster],al
  1058.  
  1059.                 ; set the number of sectors per FAT
  1060.  
  1061.                 mov ax,word ptr [si+bx+8]
  1062.                 mov word ptr [sectors_fat],ax
  1063.  
  1064.                 ; set the total number of sectors per disk
  1065.  
  1066.                 xor dx,dx
  1067.                 xor ah,ah
  1068.                 mov al,byte ptr [max_track]
  1069.                 inc ax
  1070.                 mul word ptr [sectors_track]
  1071.                 xor bh,bh
  1072.                 mov bl,byte ptr [heads]
  1073.                 mul bx
  1074.                 mov word ptr [small_total],ax
  1075.  
  1076.                 ; calculate the location of the first directory sector
  1077.  
  1078.                 xor dx,dx
  1079.                 xor ah,ah
  1080.                 mov al,byte ptr [fats]
  1081.                 mul word ptr [sectors_fat]
  1082.                 add ax,word ptr [hidden_sectors]
  1083.                 adc dx,word ptr [hidden_sectors+2]
  1084.                 add ax,word ptr [reserved_sectors]
  1085.                 adc dx,0
  1086.  
  1087.                 ; store directory start sector (absolute sector number)
  1088.  
  1089.                 mov word ptr [dir_start],ax
  1090.                 mov word ptr [dir_start+2],dx
  1091.  
  1092.                 ; calculate the location of the first data sector
  1093.  
  1094.                 xor bh,bh
  1095.                 mov bl,byte ptr [sectors_directory]
  1096.                 add ax,bx
  1097.                 adc dx,0
  1098.  
  1099.                 ; store data start sector (absolute sector number)
  1100.  
  1101.                 mov word ptr [data_start],ax
  1102.                 mov word ptr [data_start+2],dx
  1103.  
  1104.                 pop si
  1105.  
  1106. ;***********************************************************************
  1107.  
  1108.                 ; reset the disk controller
  1109.  
  1110. ;***********************************************************************
  1111.  
  1112. reset:
  1113.                 mov byte ptr [retry_count],3
  1114. reset_retry:
  1115.                 xor ah,ah
  1116.                 mov dl,byte ptr [drive_number]
  1117.  
  1118.                 int 13h
  1119.  
  1120.                 jnc short set_drive
  1121.  
  1122.                 dec byte ptr [retry_count]
  1123.  
  1124.                 jnz reset_retry
  1125.  
  1126.                 mov dx,offset reset_error
  1127.  
  1128.                 jmp write_error
  1129.  
  1130. ;***********************************************************************
  1131.  
  1132.                 ; set the drive type for format
  1133.  
  1134. ;***********************************************************************
  1135.  
  1136. set_drive:
  1137.                 mov byte ptr [retry_count],3
  1138. drive_retry:
  1139.                 mov al,byte ptr [drive_type]
  1140.                 cmp al,3
  1141.  
  1142.                 jl five_inch
  1143.  
  1144.                 mov al,4
  1145.  
  1146.                 jmp short set_type
  1147. five_inch:
  1148.                 cmp al,2
  1149.  
  1150.                 jne low_density
  1151.  
  1152.                 cmp byte ptr [disk_size],1
  1153.  
  1154.                 jg high_density
  1155.  
  1156.                 mov al,2
  1157.  
  1158.                 jmp short set_type
  1159. high_density:
  1160.                 mov al,3
  1161.  
  1162.                 jmp short set_type
  1163. low_density:
  1164.                 mov al,1
  1165. set_type:
  1166.                 mov ah,17h
  1167.  
  1168.                 int 13h
  1169.  
  1170.                 jnc short set_disk
  1171.  
  1172.                 cmp ah,80h
  1173.  
  1174.                 jne floppy_exists
  1175.  
  1176.                 mov dx,offset no_floppy_error
  1177.  
  1178.                 jmp write_error
  1179. floppy_exists:
  1180.                 dec byte ptr [retry_count]
  1181.  
  1182.                 jnz drive_retry
  1183.  
  1184.                 mov dx,offset set_drive_error
  1185.  
  1186.                 jmp write_error
  1187.  
  1188. ;***********************************************************************
  1189.  
  1190.                 ; set the disk type for format
  1191.  
  1192. ;***********************************************************************
  1193.  
  1194. set_disk:
  1195.                 mov byte ptr [retry_count],3
  1196. disk_retry:
  1197.                 push es
  1198.                 push di
  1199.                 mov ah,18h
  1200.                 mov ch,byte ptr [max_track]
  1201.                 mov cl,byte ptr [sectors_track]
  1202.                 mov dl,byte ptr [drive_number]
  1203.  
  1204.                 int 13h
  1205.  
  1206.                 pop di
  1207.                 pop es
  1208.  
  1209.                 jnc format_disk
  1210.  
  1211.                 dec byte ptr [retry_count]
  1212.  
  1213.                 jnz disk_retry
  1214.  
  1215.                 mov dx,offset set_disk_error
  1216.  
  1217.                 jmp write_error
  1218.  
  1219. ;***********************************************************************
  1220.  
  1221.                 ; format the disk
  1222.  
  1223. ;***********************************************************************
  1224.  
  1225. format_disk:
  1226.                 ; set up the loop counter
  1227.  
  1228.                 xor ch,ch
  1229.                 mov cl,byte ptr [max_track]
  1230.                 inc cx
  1231. format_loop:
  1232.                 push cx
  1233.  
  1234.                 call format_track
  1235.  
  1236.                 jnc continue
  1237.  
  1238.                 pop cx
  1239.  
  1240.                 jmp write_error
  1241. continue:
  1242.                 call next_track
  1243.  
  1244.                 pop cx
  1245.  
  1246.                 loop format_loop
  1247.  
  1248. ;***********************************************************************
  1249.  
  1250.                 ; set up the volume serial number in the boot record
  1251.  
  1252. ;***********************************************************************
  1253.  
  1254. serial_number:
  1255.                 ; get the time
  1256.  
  1257.                 mov ah,2ch
  1258.  
  1259.                 int 21h
  1260.  
  1261.                 ; fiddle the serial number bytes (similar to DOS 4.0)
  1262.                 ;
  1263.                 ; I don't know why IBM does this.  It may be done to
  1264.                 ;  hide the fact that the serial number is derived
  1265.                 ;  from the system clock.
  1266.                 ;
  1267.                 ; I am not sure that the numbers that I have chosen are
  1268.                 ;  the same as IBM's, but they are close.
  1269.                 ;
  1270.                 ; a more reasonable approach might be to simply add one
  1271.                 ;  to each byte to avoid zero bytes in the serial number
  1272.  
  1273.                 add cx,07c7h
  1274.                 add dx,0707h
  1275.  
  1276.                 ; store the serial number in the boot record
  1277.  
  1278.                 mov word ptr [sn_low],cx
  1279.                 mov word ptr [sn_high],dx
  1280.  
  1281. ;***********************************************************************
  1282.  
  1283.                 ; write the boot record and FAT1
  1284.  
  1285. ;***********************************************************************
  1286.  
  1287. write_boot:
  1288.                 mov dx,offset boot_message
  1289.                 mov ah,09h
  1290.  
  1291.                 int 21h
  1292.  
  1293.                 mov byte ptr [retry_count],3
  1294. boot_retry:
  1295.                 mov ax,0302h
  1296.                 mov bx,offset boot_record
  1297.                 mov cx,0001h
  1298.                 xor dh,dh
  1299.                 mov dl,byte ptr [drive_number]
  1300.  
  1301.                 int 13h
  1302.  
  1303.                 jnc short finish_fat1
  1304.  
  1305.                 dec byte ptr [retry_count]
  1306.  
  1307.                 jnz boot_retry
  1308.  
  1309.                 mov dx,offset write_boot_error
  1310.  
  1311.                 jmp write_error
  1312. finish_fat1:
  1313.                 mov dx,offset fat_message
  1314.                 mov ah,09h
  1315.  
  1316.                 int 21h
  1317.  
  1318.                 ; set the starting sector (absolute)
  1319.  
  1320.                 mov ax,2
  1321.                 xor dx,dx
  1322.  
  1323.                 ; set the number of sectors to write
  1324.  
  1325.                 mov cx,word ptr [sectors_fat]
  1326.                 dec cx
  1327. fat1:
  1328.                 push ax
  1329.                 push cx
  1330.                 push dx
  1331.  
  1332.                 call write_ths
  1333.  
  1334.                 jnc fat1_ths_ok
  1335.  
  1336.                 pop ax
  1337.                 pop ax
  1338.                 pop ax
  1339.  
  1340.                 mov dx,offset write_fat_error
  1341.  
  1342.                 jmp write_error
  1343. fat1_ths_ok:
  1344.                 mov bx,offset fat_dir_record
  1345.                 mov byte ptr [retry_count],3
  1346. fat1_retry:
  1347.                 call write_disk
  1348.  
  1349.                 jnc fat1_write_ok
  1350.  
  1351.                 dec byte ptr [retry_count]
  1352.  
  1353.                 jnz fat1_retry
  1354.  
  1355.                 pop ax
  1356.                 pop ax
  1357.                 pop ax
  1358.  
  1359.                 mov dx,offset write_fat_error
  1360.  
  1361.                 jmp write_error
  1362. fat1_write_ok:
  1363.                 pop dx
  1364.                 pop cx
  1365.                 pop ax
  1366.  
  1367.                 ; increment the absolute sector number
  1368.  
  1369.                 add ax,1
  1370.                 adc dx,0
  1371.  
  1372.                 loop fat1
  1373.  
  1374.                 jnc write_fat
  1375.  
  1376.                 mov dx,offset write_fat_error
  1377.  
  1378.                 jmp write_error
  1379.  
  1380. ;***********************************************************************
  1381.  
  1382.                 ; write FAT2
  1383.  
  1384. ;***********************************************************************
  1385.  
  1386. write_fat:
  1387.                 mov byte ptr [retry_count],3
  1388. fat_retry:
  1389.                 mov ax,0301h
  1390.                 mov bx,offset fat_record
  1391.                 xor ch,ch
  1392.                 mov cl,byte ptr [sectors_fat]
  1393.                 add cl,2
  1394.                 xor dh,dh
  1395.                 mov dl,byte ptr [drive_number]
  1396.  
  1397.                 int 13h
  1398.  
  1399.                 jnc finish_fat2
  1400.  
  1401.                 dec byte ptr [retry_count]
  1402.  
  1403.                 jnz fat_retry
  1404.  
  1405.                 mov dx,offset write_fat_error
  1406.  
  1407.                 jmp write_error
  1408. finish_fat2:
  1409.                 ; set the starting sector (absolute)
  1410.  
  1411.                 mov ax,2
  1412.                 xor dx,dx
  1413.                 add ax,word ptr [sectors_fat]
  1414.                 adc dx,0
  1415.  
  1416.                 ; set the number of sectors to write
  1417.  
  1418.                 mov cx,word ptr [sectors_fat]
  1419.                 dec cx
  1420. fat2:
  1421.                 push ax
  1422.                 push cx
  1423.                 push dx
  1424.  
  1425.                 call write_ths
  1426.  
  1427.                 jnc fat2_ths_ok
  1428.  
  1429.                 pop ax
  1430.                 pop ax
  1431.                 pop ax
  1432.  
  1433.                 mov dx,offset write_fat_error
  1434.  
  1435.                 jmp write_error
  1436. fat2_ths_ok:
  1437.                 mov bx,offset fat_dir_record
  1438.                 mov byte ptr [retry_count],3
  1439. fat2_retry:
  1440.                 call write_disk
  1441.  
  1442.                 jnc fat2_write_ok
  1443.  
  1444.                 dec byte ptr [retry_count]
  1445.  
  1446.                 jnz fat2_retry
  1447.  
  1448.                 pop ax
  1449.                 pop ax
  1450.                 pop ax
  1451.  
  1452.                 mov dx,offset write_fat_error
  1453.  
  1454.                 jmp short write_error
  1455. fat2_write_ok:
  1456.                 pop dx
  1457.                 pop cx
  1458.                 pop ax
  1459.  
  1460.                 ; increment the absolute sector number
  1461.  
  1462.                 add ax,1
  1463.                 adc dx,0
  1464.  
  1465.                 loop fat2
  1466.  
  1467.                 jnc write_dir
  1468.  
  1469.                 mov dx,offset write_fat_error
  1470.  
  1471.                 jmp short write_error
  1472.  
  1473. ;***********************************************************************
  1474.  
  1475.                 ; write the directory
  1476.  
  1477. ;***********************************************************************
  1478.  
  1479. write_dir:
  1480.                 mov dx,offset dir_message
  1481.                 mov ah,09h
  1482.  
  1483.                 int 21h
  1484.  
  1485.                 ; set the starting sector (absolute)
  1486.  
  1487.                 xor dx,dx
  1488.                 mov ax,word ptr [sectors_fat]
  1489.                 mul byte ptr [fats]
  1490.                 add ax,word ptr [reserved_sectors]
  1491.                 adc dx,0
  1492.  
  1493.                 ; set the number of sectors to write
  1494.  
  1495.                 xor ch,ch
  1496.                 mov cl,byte ptr [sectors_directory]
  1497. dir:
  1498.                 push ax
  1499.                 push cx
  1500.                 push dx
  1501.  
  1502.                 call write_ths
  1503.  
  1504.                 jnc dir_ths_ok
  1505.  
  1506.                 pop ax
  1507.                 pop ax
  1508.                 pop ax
  1509.  
  1510.                 mov dx,offset write_dir_error
  1511.  
  1512.                 jmp short write_error
  1513. dir_ths_ok:
  1514.                 mov bx,offset fat_dir_record
  1515.                 mov byte ptr [retry_count],3
  1516. dir_retry:
  1517.                 call write_disk
  1518.  
  1519.                 jnc dir_write_ok
  1520.  
  1521.                 dec byte ptr [retry_count]
  1522.  
  1523.                 jnz dir_retry
  1524.  
  1525.                 pop ax
  1526.                 pop ax
  1527.                 pop ax
  1528.  
  1529.                 mov dx,offset write_dir_error
  1530.  
  1531.                 jmp short write_error
  1532. dir_write_ok:
  1533.                 pop dx
  1534.                 pop cx
  1535.                 pop ax
  1536.  
  1537.                 ; increment the absolute sector number
  1538.  
  1539.                 add ax,1
  1540.                 adc dx,0
  1541.  
  1542.                 loop dir
  1543.  
  1544.                 jnc transfer
  1545.  
  1546.                 mov dx,offset write_dir_error
  1547.  
  1548.                 jmp short write_error
  1549. transfer:
  1550.                 cmp byte ptr [system],1
  1551.  
  1552.                 jne exit
  1553.  
  1554.                 ; transfer the system files
  1555.  
  1556.                 call load_system
  1557.  
  1558.                 jnc exit
  1559.  
  1560.                 ; set exit code to 5 (error copying system files)
  1561.  
  1562.                 mov ax,4c05h
  1563.                 push ax
  1564.  
  1565.                 jmp short error_exit
  1566. write_error:
  1567.                 mov ah,09h
  1568.  
  1569.                 int 21h
  1570.  
  1571.                 ; set exit code to 1 (format, verify, or write error)
  1572.  
  1573.                 mov ax,4c01h
  1574.                 push ax
  1575.  
  1576.                 jmp short error_exit
  1577.  
  1578. ;***********************************************************************
  1579.  
  1580.                 ; clean up and exit
  1581.  
  1582. ;***********************************************************************
  1583.  
  1584. exit:
  1585.                 ; set exit code to 0 (Success)
  1586.  
  1587.                 mov ax,4c00h
  1588.                 push ax
  1589. error_exit:
  1590.                 ; restore the original disk parameter table pointer
  1591.  
  1592.                 mov cx,word ptr [parameter_pointer]
  1593.                 mov dx,word ptr [parameter_pointer+2]
  1594.                 push ds
  1595.                 xor ax,ax
  1596.                 mov ds,ax
  1597.  
  1598.                 assume ds:0000h
  1599.  
  1600.                 cli
  1601.                 mov word ptr ds:[0078h],cx
  1602.                 mov word ptr ds:[007ah],dx
  1603.                 sti
  1604.                 pop ds
  1605.  
  1606.                 assume ds:cseg
  1607.  
  1608.                 ; park the heads on track 0
  1609.  
  1610.                 mov ah,0ch
  1611.                 xor cl,cl
  1612.                 xor dh,dh
  1613.                 mov dl,byte ptr [drive_number]
  1614.  
  1615.                 int 13h
  1616.  
  1617.                 pop ax
  1618.                 push ax
  1619.                 cmp al,0
  1620.  
  1621.                 jne error_out
  1622.  
  1623.                 ; display format complete message
  1624.  
  1625.                 mov dx,offset exit_message
  1626.                 mov ah,09h
  1627.  
  1628.                 int 21h
  1629. error_out:
  1630.                 ; restore the cursor
  1631.  
  1632.                 mov cx,word ptr [cursor]
  1633.                 mov ah,01h
  1634.  
  1635.                 int 10h
  1636.  
  1637.                 ; terminate with exit code (0 = Success, else = Failure)
  1638.  
  1639.                 pop ax
  1640.  
  1641.                 int 21h
  1642.  
  1643. ;***********************************************************************
  1644.  
  1645.                 ; format subroutines
  1646.  
  1647. ;***********************************************************************
  1648.  
  1649. ;***********************************************************************
  1650.  
  1651.                 ; information display during format
  1652.  
  1653. ;***********************************************************************
  1654.  
  1655. display_format:
  1656.                 xor ah,ah
  1657.                 aam
  1658.                 or ax,3030h
  1659.                 mov byte ptr [format_track_number+1],al
  1660.                 cmp ah,30h
  1661.  
  1662.                 jne format_digit
  1663.  
  1664.                 mov ah,20h
  1665. format_digit:
  1666.                 mov byte ptr [format_track_number],ah
  1667.                 mov al,bl
  1668.                 xor ah,ah
  1669.                 aam
  1670.                 or ax,3030h
  1671.                 mov byte ptr [format_head_number],al
  1672.                 mov dx,offset format_display
  1673.                 mov ah,09h
  1674.  
  1675.                 int 21h
  1676.  
  1677.                 ret
  1678.  
  1679. ;***********************************************************************
  1680.  
  1681.                 ; information display during verification
  1682.  
  1683. ;***********************************************************************
  1684.  
  1685. display_verify:
  1686.                 xor ah,ah
  1687.                 aam
  1688.                 or ax,3030h
  1689.                 mov byte ptr [verify_track_number+1],al
  1690.                 cmp ah,30h
  1691.  
  1692.                 jne verify_digit
  1693.  
  1694.                 mov ah,20h
  1695. verify_digit:
  1696.                 mov byte ptr [verify_track_number],ah
  1697.                 mov al,bl
  1698.                 xor ah,ah
  1699.                 aam
  1700.                 or ax,3030h
  1701.                 mov byte ptr [verify_head_number],al
  1702.                 mov dx,offset verify_display
  1703.                 mov ah,09h
  1704.  
  1705.                 int 21h
  1706.  
  1707.                 ret
  1708.  
  1709. ;***********************************************************************
  1710.  
  1711.                 ; increment the track number in the sector tables
  1712.  
  1713. ;***********************************************************************
  1714.  
  1715. next_track:
  1716.                 xor ch,ch
  1717.                 mov cl,36
  1718.                 mov bx,offset sector_table_0
  1719. track_counter:
  1720.                 inc byte ptr [bx]
  1721.                 add bx,4
  1722.  
  1723.                 loop track_counter
  1724.  
  1725.                 ret
  1726.  
  1727. ;***********************************************************************
  1728.  
  1729.                 ; format (and possibly verify) both heads on one track
  1730.  
  1731. ;***********************************************************************
  1732.  
  1733. format_track:
  1734.                 mov al,byte ptr [sector_table_0]
  1735.                 mov bl,0
  1736.  
  1737.                 ; display formatting message
  1738.  
  1739.                 call display_format
  1740.  
  1741.                 mov byte ptr [retry_count],3
  1742. head_0_retry:
  1743.                 mov ah,5
  1744.                 mov al,byte ptr [sectors_track]
  1745.                 mov bx,offset sector_table_0
  1746.                 mov ch,byte ptr [bx]
  1747.                 mov cl,byte ptr [bx+2]
  1748.                 mov dh,byte ptr [bx+1]
  1749.                 mov dl,byte ptr [drive_number]
  1750.  
  1751.                 int 13h
  1752.  
  1753.                 jnc short head_0_ok
  1754.  
  1755.                 cmp ah,80h
  1756.  
  1757.                 jne no_timeout
  1758.  
  1759.                 mov dx,offset no_floppy_error
  1760.                 stc
  1761.                 ret
  1762. no_timeout:
  1763.                 cmp ah,03h
  1764.  
  1765.                 jne not_protected
  1766.  
  1767.                 mov dx,offset write_protect_error
  1768.                 stc
  1769.                 ret
  1770. not_protected:
  1771.                 dec byte ptr [retry_count]
  1772.  
  1773.                 jnz head_0_retry
  1774.  
  1775.                 mov dx,offset error_during_format
  1776.                 stc
  1777.                 ret
  1778. head_0_ok:
  1779.                 cmp byte ptr [verify],1
  1780.  
  1781.                 je verify_head_0
  1782.  
  1783.                 ; check for proper floppy type
  1784.                 ;
  1785.                 ; this is done via a verification of tracks 0,
  1786.                 ;  59, and 79, for head 0 only, for all 1.2 Mb disks
  1787.                 ;  not being verified, and on track 0 head 0 only, for
  1788.                 ;  360 Kb, 720 Kb and 1.44 Mb disks not being verified.
  1789.                 ;
  1790.                 ; the following combinations will fail at track 0:
  1791.                 ;
  1792.                 ; 1: trying to format a 1.2 Mb floppy to 360 Kb
  1793.                 ; 2: trying to format a 720 Kb floppy to 1.44 Mb *
  1794.                 ; 3: trying to format a 1.44 Mb floppy to 720 Kb * !
  1795.                 ;
  1796.                 ; the following combination will fail at track 79:
  1797.                 ;
  1798.                 ; 1: trying to format a 360 Kb floppy to 1.2 Mb (it will
  1799.                 ;     probably fail sooner, but it is sure to here)
  1800.                 ;
  1801.                 ; notes:
  1802.                 ;
  1803.                 ; * - these combinations may not fail if the drive-
  1804.                 ;      controller combination does not properly detect
  1805.                 ;      the the floppy type.
  1806.                 ;
  1807.                 ; ! - this combination may not fail in 720 Kb drives.
  1808.                 ;
  1809.                 ; While certain non-standard combinations may not fail,
  1810.                 ;  either the data on the disk may be at risk, or your
  1811.                 ;  pocketbook may suffer, if you insist on using them.
  1812.  
  1813.                 cmp byte ptr [sector_table_0],0
  1814.  
  1815.                 je verify_type
  1816.  
  1817.                 cmp byte ptr [disk_size],2
  1818.  
  1819.                 je one_point_two
  1820.  
  1821.                 jmp short format_head_1
  1822. one_point_two:
  1823.                 cmp byte ptr [sector_table_0],59
  1824.  
  1825.                 je verify_type
  1826.  
  1827.                 cmp byte ptr [sector_table_0],79
  1828.  
  1829.                 je verify_type
  1830.  
  1831.                 jmp short format_head_1
  1832. verify_type:
  1833.                 mov ah,04h
  1834.  
  1835.                 int 13h
  1836.  
  1837.                 jnc format_head_1
  1838.  
  1839.                 mov dx,offset disk_type_error
  1840.                 stc
  1841.                 ret
  1842. verify_head_0:
  1843.                 pushf
  1844.                 pusha
  1845.                 mov al,byte ptr [sector_table_0]
  1846.                 mov bl,0
  1847.  
  1848.                 ; display verifying message
  1849.  
  1850.                 call display_verify
  1851.  
  1852.                 popa
  1853.                 popf
  1854.                 mov ah,04h
  1855.  
  1856.                 int 13h
  1857.  
  1858.                 jnc format_head_1
  1859.  
  1860.                 mov dx,offset verify_error
  1861.                 stc
  1862.                 ret
  1863. format_head_1:
  1864.                 pushf
  1865.                 pusha
  1866.                 mov al,byte ptr [sector_table_0]
  1867.                 mov bl,1
  1868.  
  1869.                 ; display formatting message
  1870.  
  1871.                 call display_format
  1872.  
  1873.                 popa
  1874.                 popf
  1875.                 mov byte ptr [retry_count],3
  1876. head_1_retry:
  1877.                 mov ah,5
  1878.                 mov al,byte ptr [sectors_track]
  1879.                 mov bx,offset sector_table_1
  1880.                 mov ch,byte ptr [bx]
  1881.                 mov cl,byte ptr [bx+2]
  1882.                 mov dh,byte ptr [bx+1]
  1883.                 mov dl,byte ptr [drive_number]
  1884.  
  1885.                 int 13h
  1886.  
  1887.                 jnc short head_1_ok
  1888.  
  1889.                 dec byte ptr [retry_count]
  1890.  
  1891.                 jnz head_1_retry
  1892.  
  1893.                 mov dx,offset error_during_format
  1894.                 stc
  1895.                 ret
  1896. head_1_ok:
  1897.                 cmp byte ptr [verify],1
  1898.  
  1899.                 je verify_head_1
  1900. format_return:
  1901.                 clc
  1902.                 ret
  1903. verify_head_1:
  1904.                 pushf
  1905.                 pusha
  1906.                 mov al,byte ptr [sector_table_0]
  1907.                 mov bl,1
  1908.  
  1909.                 ; display verifying message
  1910.  
  1911.                 call display_verify
  1912.  
  1913.                 popa
  1914.                 popf
  1915.                 mov ah,04h
  1916.  
  1917.                 int 13h
  1918.  
  1919.                 jnc format_return
  1920.  
  1921.                 mov dx,offset verify_error
  1922.                 stc
  1923.                 ret
  1924.  
  1925. ;***********************************************************************
  1926.  
  1927.                 ; calculate the track, head, and sector for a disk write
  1928.  
  1929. ;***********************************************************************
  1930.  
  1931. write_ths:
  1932.                 ; check for a valid absolute sector number
  1933.  
  1934.                 cmp dx,word ptr [sectors_track]
  1935.  
  1936.                 jb write_ths_ok
  1937.  
  1938.                 stc
  1939.                 ret
  1940. write_ths_ok:
  1941.                 ; calculate the sector number
  1942.  
  1943.                 div word ptr [sectors_track]
  1944.                 inc dl
  1945.  
  1946.                 ; store the sector number
  1947.  
  1948.                 mov byte ptr [write_sector],dl
  1949.  
  1950.                 ; calculate the head number and the track number
  1951.  
  1952.                 xor dx,dx
  1953.                 div word ptr [heads]
  1954.  
  1955.                 ; store the head number
  1956.  
  1957.                 mov byte ptr [write_head],dl
  1958.  
  1959.                 ; store the track number
  1960.  
  1961.                 mov word ptr [write_track],ax
  1962.  
  1963.                 clc
  1964.                 ret
  1965.  
  1966. ;***********************************************************************
  1967.  
  1968.                 ; write one sector to the disk
  1969.  
  1970. ;***********************************************************************
  1971.  
  1972. write_disk:
  1973.                 ; get the track number
  1974.  
  1975.                 mov dx,word ptr [write_track]
  1976.  
  1977.                 ; shift the upper 2 bits of the track number
  1978.                 ; into the upper 2 bits of the sector number
  1979.  
  1980.                 mov cl,06
  1981.                 shl dh,cl
  1982.  
  1983.                 ; get the sector number
  1984.  
  1985.                 or dh,byte ptr [write_sector]
  1986.  
  1987.                 mov cx,dx
  1988.                 xchg ch,cl
  1989.  
  1990.                 ; get the drive number
  1991.  
  1992.                 mov dl,byte ptr [drive_number]
  1993.  
  1994.                 ; get the head number
  1995.  
  1996.                 mov dh,byte ptr [write_head]
  1997.  
  1998.                 ; write one sector to the disk
  1999.  
  2000.                 mov ax,0301h
  2001.  
  2002.                 int 13h
  2003.  
  2004.                 ret
  2005.  
  2006. ;***********************************************************************
  2007.  
  2008.                 ; transfer system files
  2009.  
  2010. ;***********************************************************************
  2011.  
  2012. bios_source_path:
  2013.  
  2014.         db "d:\"
  2015.  
  2016.     bios_source_filename:
  2017.  
  2018.         db "IBMBIO.COM",000h,008h
  2019.         db "$"
  2020.  
  2021. bios_destination_path:
  2022.  
  2023.         db "d:\"
  2024.  
  2025.     bios_destination_filename:
  2026.  
  2027.         db "IBMBIO.COM",000h,008h
  2028.         db "$"
  2029.  
  2030. dos_source_path:
  2031.  
  2032.         db "d:\"
  2033.  
  2034.     dos_source_filename:
  2035.  
  2036.         db "IBMDOS.COM",000h,008h
  2037.         db "$"
  2038.  
  2039. dos_destination_path:
  2040.  
  2041.         db "d:\"
  2042.  
  2043.     dos_destination_filename:
  2044.  
  2045.         db "IBMDOS.COM",000h,008h
  2046.         db "$"
  2047.  
  2048. cmd_source_path:
  2049.  
  2050.         db "d:\"
  2051.  
  2052.     cmd_source_filename:
  2053.  
  2054.         db "COMMAND.COM",000h,008h
  2055.         db "$"
  2056.  
  2057. cmd_destination_path:
  2058.  
  2059.         db "d:\"
  2060.  
  2061.     cmd_destination_filename:
  2062.  
  2063.         db "COMMAND.COM",000h,008h
  2064.         db "$"
  2065.  
  2066. load_system:
  2067.                 mov dx,offset file_copy_message
  2068.                 mov ah,09h
  2069.  
  2070.                 int 21h
  2071.  
  2072.                 ; get default drive
  2073.  
  2074.                 mov ah,19h
  2075.  
  2076.                 int 21h
  2077.  
  2078.                 ; set source drive
  2079.  
  2080.                 add al,41h
  2081.                 mov byte ptr [bios_source_path],al
  2082.                 mov byte ptr [dos_source_path],al
  2083.                 mov byte ptr [cmd_source_path],al
  2084.  
  2085.                 ; set destination drive
  2086.  
  2087.                 mov al,byte ptr [drive_number]
  2088.                 add al,41h
  2089.                 mov byte ptr [bios_destination_path],al
  2090.                 mov byte ptr [dos_destination_path],al
  2091.                 mov byte ptr [cmd_destination_path],al
  2092.  
  2093.                 ; copy IBMBIOS.COM
  2094.  
  2095.                 mov bx,offset file_buffer
  2096.                 mov cx,word ptr [buffer_size]
  2097.                 mov si,offset bios_source_path
  2098.                 mov di,offset bios_destination_path
  2099.  
  2100.                 call file_copy
  2101.  
  2102.                 jc load_error
  2103.  
  2104.                 ; copy IBMDOS.COM
  2105.  
  2106.                 mov bx,offset file_buffer
  2107.                 mov cx,word ptr [buffer_size]
  2108.                 mov si,offset dos_source_path
  2109.                 mov di,offset dos_destination_path
  2110.  
  2111.                 call file_copy
  2112.  
  2113.                 jc load_error
  2114.  
  2115.                 ; copy COMMAND.COM
  2116.  
  2117.                 mov bx,offset file_buffer
  2118.                 mov cx,word ptr [buffer_size]
  2119.                 mov si,offset cmd_source_path
  2120.                 mov di,offset cmd_destination_path
  2121.  
  2122.                 call file_copy
  2123.  
  2124.                 jc load_error
  2125.  
  2126.                 clc
  2127.                 ret
  2128. load_error:
  2129.                 stc
  2130.                 ret
  2131.  
  2132. ;***********************************************************************
  2133.  
  2134.                 ; copy a file
  2135.                 ;
  2136.                 ; input:
  2137.                 ;
  2138.                 ;  bx = pointer to copy buffer
  2139.                 ;  cx = copy buffer size in bytes
  2140.                 ;  si = pointer to source path\filename
  2141.                 ;  di = pointer to destination path\filename
  2142.  
  2143. ;***********************************************************************
  2144.  
  2145. source:                 dw ?
  2146. destination:            dw ?
  2147. read_handle:            dw ?
  2148. write_handle:           dw ?
  2149. file_time:              dw ?
  2150. file_date               dw ?
  2151. file_attr:              dw ?
  2152. bytes_read:             dw ?
  2153. copy_buffer_size:       dw ?
  2154. copy_buffer:            dw ?
  2155.  
  2156. ; file copy messages
  2157.  
  2158. file_not_found:
  2159.  
  2160.         db " - error opening input file",00Dh,00Ah
  2161.         db "$"
  2162.  
  2163. file_create_error:
  2164.  
  2165.         db " - error creating output file",00Dh,00Ah
  2166.         db "$"
  2167.  
  2168. file_read_error:
  2169.  
  2170.         db " - error reading file",00Dh,00Ah
  2171.         db "$"
  2172.  
  2173. file_write_error:
  2174.  
  2175.         db " - error writing file",00Dh,00Ah
  2176.         db "$"
  2177.  
  2178. file_copy:
  2179.                 mov word ptr [copy_buffer],bx
  2180.                 mov word ptr [copy_buffer_size],cx
  2181.                 mov word ptr [source],si
  2182.                 mov word ptr [destination],di
  2183.                 mov dx,word ptr [source]
  2184.                 mov ah,3dh
  2185.                 xor al,al
  2186.  
  2187.                 int 21h                         ; open source file
  2188.  
  2189.                 mov word ptr [read_handle],ax
  2190.  
  2191.                 jnc file_open
  2192.  
  2193.                 ; display file not found message
  2194.  
  2195.                 mov dx,offset cr_lf
  2196.  
  2197.                 call write_message
  2198.  
  2199.                 mov dx,word ptr [source]
  2200.  
  2201.                 call write_message
  2202.  
  2203.                 mov dx,offset file_not_found
  2204.  
  2205.                 call write_message
  2206.  
  2207.                 jmp load_error
  2208. file_open:
  2209.                 mov ax,5700h
  2210.                 mov bx,word ptr [read_handle]
  2211.  
  2212.                 int 21h                         ; get file time and date
  2213.  
  2214.                 mov word ptr [file_time],cx
  2215.                 mov word ptr [file_date],dx
  2216.                 mov ax,4300h
  2217.                 mov dx,word ptr [source]
  2218.  
  2219.                 int 21h                         ; get file attributes
  2220.  
  2221.                 mov word ptr [file_attr],cx
  2222.                 mov al,byte ptr [drive_number]
  2223.                 mov cx,0000h
  2224.                 mov dx,word ptr [destination]
  2225.                 mov ah,3ch
  2226.  
  2227.                 int 21h                         ; create destination file
  2228.  
  2229.                 mov word ptr [write_handle],ax
  2230.  
  2231.                 jnc copy_cmd
  2232.  
  2233.                 ; display file not created message
  2234.  
  2235.                 mov dx,offset cr_lf
  2236.  
  2237.                 call write_message
  2238.  
  2239.                 mov dx,word ptr [destination]
  2240.  
  2241.                 call write_message
  2242.  
  2243.                 mov dx,offset file_create_error
  2244.  
  2245.                 call write_message
  2246.  
  2247.                 jmp copy_error
  2248. copy_cmd:
  2249.                 call read_file
  2250.  
  2251.                 jnc file_read_ok
  2252.  
  2253.                 ; display file read error message
  2254.  
  2255.                 mov dx,offset cr_lf
  2256.  
  2257.                 call write_message
  2258.  
  2259.                 mov dx,word ptr [source]
  2260.  
  2261.                 call write_message
  2262.  
  2263.                 mov dx,offset file_read_error
  2264.  
  2265.                 call write_message
  2266.  
  2267.                 jmp copy_error
  2268. file_read_ok:
  2269.                 call write_file
  2270.  
  2271.                 jnc file_write_ok
  2272.  
  2273.                 ; display file write error message
  2274.  
  2275.                 mov dx,offset cr_lf
  2276.  
  2277.                 call write_message
  2278.  
  2279.                 mov dx,word ptr [destination]
  2280.  
  2281.                 call write_message
  2282.  
  2283.                 mov dx,offset file_write_error
  2284.  
  2285.                 call write_message
  2286.  
  2287.                 jmp copy_error
  2288. file_write_ok:
  2289.                 cmp ax,word ptr [copy_buffer_size]
  2290.  
  2291.                 je copy_cmd
  2292.  
  2293.                 mov bx,word ptr [read_handle]
  2294.                 mov ah,3eh
  2295.  
  2296.                 int 21h                         ; close read_file
  2297.  
  2298.                 mov ax,5701h
  2299.                 mov bx,word ptr [write_handle]
  2300.                 mov cx,word ptr [file_time]
  2301.                 mov dx,word ptr [file_date]
  2302.  
  2303.                 int 21h                         ; set file time and date
  2304.  
  2305.                 mov bx,word ptr [write_handle]
  2306.                 mov ah,3eh
  2307.  
  2308.                 int 21h                         ; close write_file
  2309.  
  2310.                 mov ax,4301h
  2311.                 mov cx,word ptr [file_attr]
  2312.                 mov dx,word ptr [destination]
  2313.  
  2314.                 int 21h                         ; set file attributes
  2315.  
  2316.                 clc
  2317.                 ret
  2318. copy_error:
  2319.                 stc
  2320.                 ret
  2321.  
  2322. ;***********************************************************************
  2323.  
  2324.                 ; issue a file copy error message
  2325.  
  2326. ;***********************************************************************
  2327.  
  2328. write_message:
  2329.                 mov ah,09h
  2330.  
  2331.                 int 21h
  2332.  
  2333.                 ret
  2334.  
  2335. ;***********************************************************************
  2336.  
  2337.                 ; read file block into buffer
  2338.  
  2339. ;***********************************************************************
  2340.  
  2341. read_file:
  2342.                 mov cx,word ptr [copy_buffer_size]
  2343.                 mov bx,word ptr [read_handle]
  2344.                 mov dx,word ptr [copy_buffer]
  2345.                 mov ah,3fh
  2346.  
  2347.                 int 21h
  2348.  
  2349.                 mov word ptr [bytes_read],ax
  2350.                 mov cx,ax
  2351.                 ret
  2352.  
  2353. ;***********************************************************************
  2354.  
  2355.                 ; write file block from buffer
  2356.  
  2357. ;***********************************************************************
  2358.  
  2359. write_file:
  2360.                 mov bx,word ptr [write_handle]
  2361.                 mov dx,word ptr [copy_buffer]
  2362.                 mov ah,40h
  2363.  
  2364.                 int 21h
  2365.  
  2366.                 ret
  2367.  
  2368. ;***********************************************************************
  2369.  
  2370.                 ; boot sector data (track 0, head 0, sector 1)
  2371.  
  2372. ;***********************************************************************
  2373.  
  2374. boot_record:
  2375.  
  2376. ;***********************************************************************
  2377.  
  2378. .8086           ; enable the 8086 instruction set
  2379.  
  2380. ;***********************************************************************
  2381.  
  2382.                 jmp boot_strap          ; skip over data areas
  2383.  
  2384. ;***********************************************************************
  2385.  
  2386.                 ; DOS data area
  2387.  
  2388. ;***********************************************************************
  2389.  
  2390. oem_name:               db   "FMT 1.00"
  2391. bytes_sector:           dw   512
  2392. sectors_cluster:        db   ?          ; filled in before writing boot
  2393. reserved_sectors:       dw   1
  2394. fats:                   db   2
  2395. directory_size:         dw   ?          ; filled in before writing boot
  2396. small_total:            dw   ?          ; filled in before writing boot
  2397. descriptor:             db   ?          ; filled in before writing boot
  2398. sectors_fat:            dw   ?          ; filled in before writing boot
  2399. sectors_track:          dw   ?          ; filled in before writing boot
  2400. heads:                  dw   2
  2401. hidden_sectors:         dd   0
  2402. big_total:              dd   0
  2403. physical_drive:         db   0
  2404. reserved:               db   0
  2405. extended_boot:          db   029h
  2406. sn_low:                 dw   ?          ; filled in before writing boot
  2407. sn_high:                dw   ?          ; filled in before writing boot
  2408. volume_label:           db   "NO NAME    "
  2409. fat_type:               db   "FAT12   "
  2410.  
  2411. ;***********************************************************************
  2412.  
  2413.                 ; bootstrap program data area
  2414.  
  2415. ;***********************************************************************
  2416.  
  2417. sectors_directory:      db ?            ; filled in before writing boot
  2418. dir_start:              dd ?            ; filled in before writing boot
  2419. data_start:             dd ?            ; filled in before writing boot
  2420. track:                  dw ?            ; boot program variable
  2421. head:                   db ?            ; boot program variable
  2422. sector:                 db ?            ; boot program variable
  2423. disk_table:             db 11 dup (?)   ; filled in before writing boot
  2424.  
  2425. bios_name:              db "IBMBIO  COM"
  2426.  
  2427. dos_name:               db "IBMDOS  COM"
  2428.  
  2429.                         ; boot program messages
  2430. reset_message:
  2431.                         db 00Dh,00Ah,00Ah
  2432.                         db "Disk controller error ..."
  2433.                         db 000h
  2434.  
  2435. system_message:
  2436.                         db 00Dh,00Ah,00Ah
  2437.                         db "No system on disk or disk read error ..."
  2438.                         db 000h
  2439.  
  2440. retry_message:
  2441.                         db 00Dh,00Ah,00Ah
  2442.                         db "Press any key to retry boot."
  2443.                         db 000h
  2444.  
  2445. ;***********************************************************************
  2446.  
  2447. boot_strap:
  2448.                 ; temporarily disable interrupts
  2449.  
  2450.                 cli
  2451.  
  2452.                 ; set the stack segment and the extra segment to 0000
  2453.                 ; DOS loads the boot record at 0000:7c00,
  2454.                 ; so put the stack just below it
  2455.  
  2456.                 xor ax,ax
  2457.                 mov es,ax
  2458.                 mov ss,ax
  2459.                 mov sp,7c00h
  2460.  
  2461.                 assume es:0000h,ss:0000h
  2462.  
  2463.                 ; set up the parameters used by the BIOS program loader
  2464.  
  2465.                 lds si,es:[0078h]
  2466.                 mov bx,0078h
  2467.  
  2468.                 ; save current disk parameter table
  2469.  
  2470.                 push ds
  2471.                 push si
  2472.                 push ss
  2473.                 push bx
  2474.  
  2475.                 ; set the data segment to 0000
  2476.  
  2477.                 mov ds,ax
  2478.  
  2479.                 assume ds:0000h
  2480.  
  2481.                 ; use the disk parameter table in the floppy boot record
  2482.  
  2483.                 mov word ptr [bx],7c00h+disk_table-boot_record
  2484.                 mov word ptr [bx+02],ax
  2485.  
  2486.                 ; enable interrupts
  2487.  
  2488.                 sti
  2489.  
  2490.                 ; reset the disk controller
  2491.  
  2492.                 int 13h
  2493.  
  2494.                 jnc reset_ok
  2495.  
  2496.                 ; display reset error message
  2497.  
  2498.                 mov si,7c00h+offset reset_message-offset boot_record
  2499.  
  2500.                 call write_string
  2501.  
  2502.                 jmp not_bootable
  2503. reset_ok:
  2504.                 ; get directory start sector (absolute sector number)
  2505.  
  2506.                 mov ax,word ptr ds:[7c00h+dir_start-boot_record]
  2507.                 mov dx,word ptr ds:[7c00h+dir_start-boot_record+2]
  2508.  
  2509.                 ; get track, head, and sector
  2510.  
  2511.                 call calculate_ths
  2512.  
  2513.                 jnc dir_sector_ok
  2514.  
  2515.                 ; display system error message
  2516.  
  2517.                 mov si,7c00h+offset system_message-offset boot_record
  2518.  
  2519.                 call write_string
  2520.  
  2521.                 jmp not_bootable
  2522. dir_sector_ok:
  2523.                 ; set the offset of the disk read buffer
  2524.  
  2525.                 mov bx,0500h
  2526.  
  2527.                 ; read the first directory sector
  2528.  
  2529.                 call read_disk
  2530.  
  2531.                 jc not_bootable
  2532.  
  2533.                 ; check directory for the BIOS file
  2534.                 ; (it must be the first directory entry)
  2535.  
  2536.                 mov di,bx
  2537.                 mov cx,11
  2538.                 mov si,7c00h+offset bios_name-offset boot_record
  2539.  
  2540.                 rep cmpsb
  2541.  
  2542.                 jz dir_read_ok
  2543.  
  2544.                 ; display system error message
  2545.  
  2546.                 mov si,7c00h+offset system_message-offset boot_record
  2547.  
  2548.                 call write_string
  2549.  
  2550.                 jmp not_bootable
  2551. dir_read_ok:
  2552.                 ; check directory for the DOS file
  2553.                 ; (it must be the second directory entry)
  2554.  
  2555.                 lea di,[bx+32]
  2556.                 mov si,7c00h+offset dos_name-offset boot_record
  2557.                 mov cx,11
  2558.  
  2559.                 rep cmpsb
  2560.  
  2561.                 ; valid directory, attempt to boot from the disk
  2562.  
  2563.                 jz system_found
  2564.  
  2565.                 ; display system error message
  2566.  
  2567.                 mov si,7c00h+offset system_message-offset boot_record
  2568.  
  2569.                 call write_string
  2570.  
  2571.                 jmp not_bootable
  2572.  
  2573. ;***********************************************************************
  2574.  
  2575. system_found:
  2576.                 ; get the data start sector (absolute sector number)
  2577.  
  2578.                 mov ax,word ptr ds:[7c00h+data_start-boot_record]
  2579.                 mov dx,word ptr ds:[7c00h+data_start-boot_record+2]
  2580.  
  2581.                 ; set the offset of the disk read buffer
  2582.  
  2583.                 mov bx,0700h
  2584.  
  2585.                 ; read 3 sectors (the length of the BIOS program loader)
  2586.  
  2587.                 mov cx,3
  2588. read_next:
  2589.                 push ax
  2590.                 push cx
  2591.                 push dx
  2592.  
  2593.                 ; get track, head, and sector
  2594.  
  2595.                 call calculate_ths
  2596.  
  2597.                 jnb ok_to_read
  2598.  
  2599.                 ; clean up the stack
  2600.  
  2601.                 pop ax
  2602.                 pop ax
  2603.                 pop ax
  2604.  
  2605.                 ; display system error message
  2606.  
  2607.                 mov si,7c00h+offset system_message-offset boot_record
  2608.  
  2609.                 call write_string
  2610.  
  2611.                 jmp not_bootable
  2612. ok_to_read:
  2613.                 call read_disk
  2614.  
  2615.                 pop dx
  2616.                 pop cx
  2617.                 pop ax
  2618.  
  2619.                 jnc disk_read_ok
  2620.  
  2621.                 ; display system error message
  2622.  
  2623.                 mov si,7c00h+offset system_message-offset boot_record
  2624.  
  2625.                 call write_string
  2626.  
  2627.                 jmp not_bootable
  2628. disk_read_ok:
  2629.                 ; increment the sector to read
  2630.  
  2631.                 add ax,1
  2632.                 adc dx,0
  2633.  
  2634.                 ; bump the offset of the read buffer by the sector size
  2635.  
  2636.                 add bx,word ptr ds:[7c00h+bytes_sector-boot_record]
  2637.  
  2638.                 loop read_next
  2639.  
  2640.                 ; set up the parameters for the BIOS program loader
  2641.  
  2642.                 ; get the media descriptor
  2643.  
  2644.                 mov ch,byte ptr ds:[7c00h+descriptor-boot_record]
  2645.  
  2646.                 ; get the drive number
  2647.  
  2648.                 mov dl,byte ptr ds:[7c00h+physical_drive-boot_record]
  2649.  
  2650.                 ; get the data start sector (absolute sector number)
  2651.  
  2652.                 mov ax,word ptr ds:[7c00h+data_start-boot_record+2]
  2653.                 mov bx,word ptr ds:[7c00h+data_start-boot_record]
  2654.  
  2655.                 ; execute the BIOS program loader
  2656.  
  2657.                 jmp far ptr program_loader
  2658.  
  2659. ;***********************************************************************
  2660.  
  2661. not_bootable:
  2662.                 ; display retry message
  2663.  
  2664.                 mov si,7c00h+offset retry_message-offset boot_record
  2665.  
  2666.                 call write_string
  2667.  
  2668.                 ; wait for a key to be pressed
  2669.  
  2670.                 xor ah,ah
  2671.  
  2672.                 int 16h
  2673.  
  2674.                 ; clean up the stack
  2675.  
  2676.                 pop si
  2677.                 pop ds
  2678.                 pop [si]
  2679.                 pop [si+2]
  2680.  
  2681.                 ; try to boot the system again
  2682.  
  2683.                 int 19h
  2684.  
  2685. ;***********************************************************************
  2686.  
  2687.                 ; bootstrap subroutines
  2688.  
  2689. ;***********************************************************************
  2690.  
  2691. write_string:
  2692.                 ; get one character
  2693.  
  2694.                 lodsb
  2695.  
  2696.                 ; check for end of ASCIIZ string
  2697.  
  2698.                 or al,al
  2699.  
  2700.                 jnz next_char
  2701.  
  2702.                 ret
  2703. next_char:
  2704.                 ; write one character to the screen
  2705.  
  2706.                 mov ah,0eh
  2707.  
  2708.                 ; use video page 0, normal white
  2709.  
  2710.                 mov bx,0007h
  2711.  
  2712.                 int 10h
  2713.  
  2714.                 jmp write_string
  2715.  
  2716. ;***********************************************************************
  2717.  
  2718. read_disk:
  2719.                 ; get the track number
  2720.  
  2721.                 mov dx,word ptr ds:[7c00h+track-boot_record]
  2722.  
  2723.                 ; shift the upper 2 bits of the track number
  2724.                 ; into the upper 2 bits of the sector number
  2725.  
  2726.                 mov cl,06
  2727.                 shl dh,cl
  2728.  
  2729.                 ; get the sector number
  2730.  
  2731.                 or dh,byte ptr ds:[7c00h+sector-boot_record]
  2732.  
  2733.                 mov cx,dx
  2734.                 xchg ch,cl
  2735.  
  2736.                 ; get the drive number
  2737.  
  2738.                 mov dl,byte ptr ds:[7c00h+physical_drive-boot_record]
  2739.  
  2740.                 ; get the head number
  2741.  
  2742.                 mov dh,byte ptr ds:[7c00h+head-boot_record]
  2743.  
  2744.                 ; read one sector from the disk
  2745.  
  2746.                 mov ax,0201h
  2747.  
  2748.                 int 13h
  2749.  
  2750.                 ret
  2751.  
  2752. ;***********************************************************************
  2753.  
  2754. calculate_ths:
  2755.                 ; check for valid absolute sector number
  2756.  
  2757.                 cmp dx,word ptr ds:[7c00h+sectors_track-boot_record]
  2758.  
  2759.                 jb ths_ok
  2760.  
  2761.                 stc
  2762.                 ret
  2763. ths_ok:
  2764.                 ; calculate the sector number
  2765.  
  2766.                 div word ptr ds:[7c00h+sectors_track-boot_record]
  2767.                 inc dl
  2768.  
  2769.                 ; store the sector number
  2770.  
  2771.                 mov byte ptr ds:[7c00h+sector-boot_record],dl
  2772.  
  2773.                 ; calculate the head number and the track number
  2774.  
  2775.                 xor dx,dx
  2776.                 div word ptr ds:[7c00h+heads-boot_record]
  2777.  
  2778.                 ; store the head number
  2779.  
  2780.                 mov byte ptr ds:[7c00h+head-boot_record],dl
  2781.  
  2782.                 ; store the track number
  2783.  
  2784.                 mov word ptr ds:[7c00h+track-boot_record],ax
  2785.  
  2786.                 clc
  2787.                 ret
  2788.  
  2789. ;***********************************************************************
  2790.  
  2791.                 ; adjust the boot record size to 512 bytes
  2792.  
  2793. ;***********************************************************************
  2794.  
  2795. fill:           db (512-(offset fill-offset boot_record)-2) dup (0)
  2796.  
  2797. ;***********************************************************************
  2798.  
  2799.                 ; boot sector signature
  2800.  
  2801. ;***********************************************************************
  2802.  
  2803. signature:      dw 0AA55h
  2804.  
  2805. ;***********************************************************************
  2806.  
  2807.                 ; end of boot sector data
  2808.  
  2809. ;***********************************************************************
  2810.  
  2811. ;***********************************************************************
  2812.  
  2813.                 ; FAT and directory data
  2814.  
  2815. ;***********************************************************************
  2816.  
  2817.                 ; the first FAT sector has the media descriptor byte
  2818. fat_record:
  2819.                 db ?                    ; filled in before writing FAT
  2820.                 db 0ffh,0ffh
  2821.                 db 509 dup (0)
  2822.  
  2823.                 ; other FAT sectors and directory sectors are all zeros
  2824. fat_dir_record:
  2825.                 db 512 dup (0)
  2826.  
  2827. ;***********************************************************************
  2828.  
  2829.                 ; copyright information
  2830.  
  2831. ;***********************************************************************
  2832.  
  2833. version:        db "FMT version 1.00 23-JAN-1990",000h
  2834.  
  2835. copyright:      db "Copyright (C) 1990  by Clair Alan Hardesty",000h
  2836.  
  2837. ;***********************************************************************
  2838.  
  2839.                 ; put file copy buffer after code and other data
  2840.  
  2841. ;***********************************************************************
  2842.  
  2843. file_buffer:
  2844.                 ; buffer space starts here
  2845.  
  2846. cseg            ends
  2847.  
  2848. end             entry_point
  2849.  
  2850. ;***********************************************************************
  2851.  
  2852.                 ; end of Fmt.asm
  2853.  
  2854. ;***********************************************************************
  2855.